package main

import (
	"fmt"
	"reflect"
)

// reflect包实现了运行时反射, 允许程序操作任意类型的对象. 典型用法是用静态类型interface{}保存一个值,
// 通过调用TypeOf获取齐动态类型信息, 该函数返回一个Type类型值;
// 通过调用ValueOf函数返回一个Value类型值, 该值代表运行时的数据.
// Zero接受一个Type类型参数并返回一个代表该类型零值的Value类型值.

// 1、反射可以在运行时动态获取变量的各种信息, 比如变量的类型、类别
// 2、如果是结构体变量, 还可以获取到结构体本身的信息(包括结构体的字段、方法)
// 3、通过反射, 可以修改变量的值, 可以调用关联的方法

// 反射的应用场景
// 1、不知道接口调用哪个函数, 根据传入参数在运行时确定调用的具体接口, 这种需要对函数或方法反射
// 例如桥接模式: func bridge(funcPtr interface{}, args... interface{})
// 第一个参数funcPtr以接口的形式传入函数指针, 函数参数args以可变参数的形式传入
// bridge函数中可以用反射来动态执行funcPtr函数
// 2、对结构体序列化时, 如果结构体有指定tag, 也会使用到反射生成对应的字符串
// 3、变量、interface{}和reflect.Value是可以相互转换的
// func test(i interface{}) {
// rValue := reflect.ValueOf(i)  // 将interface{}转成reflect.Value
// iValue := rValue.Interface()  // 将reflect.Value转成interface{}
// }

func ReflectDemo(i interface{}) {
	// 通过反射获取传入变量的type、kind、value
	// 1、先获取到reflect.Type
	rType := reflect.TypeOf(i)
	fmt.Printf("%v, %T\n", rType, rType) // int, *reflect.rtype

	// 2、获取到reflect.Value
	rVal := reflect.ValueOf(i)
	fmt.Printf("%v, %T\n", rVal, rVal) // 1, reflect.Value
}

func main() {
	ReflectDemo(1)
}
